package bluetooth;

import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;

/**
 * Klasa jest odpowiedzialna za przechowywanie informacji oraz przedstawianie
 * polczenia miedzy serwerem i klientem.
 * Zarowno serwer jaki i klient posiada obiekty <code>BtConnetion</code>:
 * <ul>
 * <li>Serwer zawiera wektor obiektow <code>BtConnetion</code> odpowiadajacych
 * za polaczenia ze wszystkimi uzytkownikami</li>
 * <li>Klient zawiera jeden obiekt <code>BtConnetion</code> odpowiadajacym za
 * polaczenie z serwerem</li>
 * </ul>
 * @author      Przemyslaw Bierut
 * @version     1.0
 */
public class BtConnection {

    private StreamConnection stream;
    private DataInputStream in;
    private DataOutputStream out;
    private BtListener btListener;
    private String deviceAdress;

    /**
     * Kostruktor wykorzystywany przez obiekt typu <code>Server</code>.
     * @param _streamConnection strumien polaczeniu
     * @param _btListener obiekt nasluchujacy zdarzen z plynacych z polaczenia
     */
    public BtConnection(StreamConnection _streamConnection, BtListener _btListener) {
        init(_streamConnection, _btListener);
    }

    /**
     * Kostruktor wykorzystywany przez obiekt typu <code>Client</code>.
     * @param _url adres z którym chcemy nawiązać połączenie
     * @param _btListener obiekt nasluchujacy zdarzen z plynacych z polaczenia
     */
    public BtConnection(String _url, BtListener _btListener) {
        try {
            init((StreamConnection) Connector.open(_url), _btListener);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Metoda zwracająca adres urzadzenia z którym nawiązane jest polaczenie.
     * @return adres bluetooth
     */
    public String getBtAdress() {
        return deviceAdress;
    }

    /**
     * Metoda wysyla dane do polaczonego uzytkownika.
     * @param data dane do wyslania
     */
    public void sendData(String data) {
        try {
            if (out != null) {
                out.writeUTF(data);
                out.flush();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            close();
        }
    }

    /**
     * Metoda sprzatajaca po polaczeniu.
     */
    public void close() {
        try {
            stream.close();
            in.close();
            out.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void init(StreamConnection _streamConnection, BtListener _btListener) {
        try {
            btListener = _btListener;
            stream = _streamConnection;
            deviceAdress = RemoteDevice.getRemoteDevice(stream).getBluetoothAddress();
            in = stream.openDataInputStream();
            out = stream.openDataOutputStream();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        Thread receiver = new Thread() {

            @Override
            public void run() {
                while (true) {
                    try {
                        btListener.dataReceived(in.readUTF(), deviceAdress);
                    } catch (IOException ex) {
                        btListener.connectionLost(deviceAdress);
                        close();
                        break;
                    }
                }
            }
        };
        receiver.start();
    }
}
